local Obj        = require("core.Obj")
local Timer        = require("core.Timer")
local SkillExcel     = require("excel.Skill").Skill
local Skill        = require("skill.Skill")
local Status       = require("scene.Status")
local RoleDefine = require("role.RoleDefine")
local floor        = math.floor
local min        = math.min
local max        = math.max


function getCoolDown(obj, skillid)    
  local userData      = Skill.getUserData(obj)
  for i = 0, userData.cooldownLen - 1 do
    if userData.cooldown[i].id == skillid then
        return userData.cooldown[i]
    end
  end
end


function newCoolDown(obj)
    local userData      = Skill.getUserData(obj)
    if obj.obj_type == Obj.TYPE_HUMAN then
        local now = Timer.now
        local cooldownInfo
        local skillConfig
        obj.db.cooldownLen = obj.db.cooldownLen + 1
        if obj.db.cooldownLen > 45 then
            obj.db.cooldownLen = 45
            for i = 0, obj.db.cooldownLen -1 do
                cooldownInfo = userData.cooldown[i]
                skillConfig = SkillExcel[cooldownInfo.id]
                if now - cooldownInfo.time > skillConfig.coolDown then
                    return cooldownInfo
                end
            end
        end
        userData.cooldownLen = obj.db.cooldownLen      
            
    else
        userData.cooldown[userData.cooldownLen] = {id = 0, count = 0, time = 0}
        userData.cooldownLen = userData.cooldownLen + 1
    end
    return userData.cooldown[userData.cooldownLen-1]
end

-- 计算冷却
function calcCoolDown(obj,skillID)
  local skillConfig = SkillExcel[skillID]
  if skillConfig.coolDownCount >1 then  --冷却豆子处理
    local now      = Timer.now
    local cooldownInfo    = getCoolDown(obj, skillID)
    if not cooldownInfo then
      cooldownInfo = newCoolDown(obj)
      cooldownInfo.id = skillID
      cooldownInfo.count = skillConfig.coolDownCount
      cooldownInfo.time  = now
    else
      if cooldownInfo.count >= skillConfig.coolDownCount then
        cooldownInfo.time = now
        return
      end
      local time    = now - cooldownInfo.time --计算出冷却了多少时间
      local coolDown  = skillConfig.coolDown
      local count   = floor(time/coolDown)
      cooldownInfo.count  = min(cooldownInfo.count+count,skillConfig.coolDownCount)
      if count>0 then
        local offsetTime    = time%coolDown
        cooldownInfo.time = now - offsetTime
      end
    end
    
    cooldownInfo.count = max(cooldownInfo.count, 0)   
    if skillConfig.coolDownCount == cooldownInfo.count  then
      cooldownInfo.time = now
    end
  end
end

-- 冷却处理
function doCoolDown(obj, skillID, skillConfig)
  skillConfig = skillConfig or SkillExcel[skillID]
  local userData     = Skill.getUserData(obj)
  local cooldownInfo    = getCoolDown(obj, skillID)
  local currentCount    = cooldownInfo and cooldownInfo.count or skillConfig.coolDownCount
  local offsetTime = 0    
  if obj.obj_type == Obj.TYPE_HUMAN then  --技能冷却降低
    offsetTime = offsetTime + (obj.attr[RoleDefine.SKILL_COOL_DOWN] or 0) * 1000
  end
  
  if not cooldownInfo then  --添加新cooldown
      cooldownInfo = newCoolDown(obj)
  end  
  cooldownInfo.id = skillID
  
  if skillConfig.coolDownCount >1 then  --冷却豆子处理
    cooldownInfo.count = currentCount - 1
  else
    cooldownInfo.time = Timer.now  - offsetTime
    cooldownInfo.count = 0
  end

  userData.normalSkillLastTime = Timer.now    -- 普攻
  if skillConfig.isNormal == 0 then 
    userData.skillLastTime = Timer.now 
  end
  userData.lastSkillID = skillID
end


-- 能否使用技能
function canUse(obj, skillID)
  local skillConfig = SkillExcel[skillID]
  if not skillConfig then assert(nil, skillID) end
  if not Status.canSkill(obj, skillID, skillConfig) then return false end   --晕眩等不能使用技能
  local now = Timer.now
  local userData = Skill.getUserData(obj)
  
  if skillConfig.isNormal==0 then
    if now - userData.skillLastTime < 500 then  --非普攻公共冷却
      return
    end
  else
    if now - userData.normalSkillLastTime < userData.normalSkillCommonCooldown then  --普攻公共冷却
      return
    end 
  end
  calcCoolDown(obj, skillID)  --重新计算冷却豆子
  
  local cooldownInfo    = getCoolDown(obj, skillID)
  if cooldownInfo and now - cooldownInfo.time < skillConfig.coolDown then
    if skillConfig.coolDownCount >1 then  --冷却豆子处理
      if cooldownInfo.count>0 then
        return true
      end
    end
    return    --技能冷却中
  end
  return true
end

function getSkillNextCanUseTime(obj, skillID)
  local skillConfig = SkillExcel[skillID]
  if not skillConfig then
    assert(nil, skillID)
  end
  local cooldownInfo    = getCoolDown(obj, skillID)
  local ret = 0
  if cooldownInfo then
    ret  = cooldownInfo.time + skillConfig.coolDown
  end
  if not Status.canSkill(obj, skillID, skillConfig) then
    ret = ret + Timer.now
  end   
  return ret
end

function getSkillCoolDownTime(obj, skillID)
  local skillConfig = SkillExcel[skillID]
  if not skillConfig then
    return 0
  end
  local userData = Skill.getUserData(obj)
  if not userData then
    return 0
  end
  local cooldownInfo    = getCoolDown(obj, skillID)
  if not cooldownInfo then
    return 0
  end
  local now = Timer.now
  if now - cooldownInfo.time < skillConfig.coolDown then
    return skillConfig.coolDown + cooldownInfo.time - now
  end 
  return 0
end